package com.fjwt.gz.proxy.secruity;

import com.fjwt.gz.proxy.config.SystemYmlConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

@Configuration
@EnableWebSecurity
@EnableMethodSecurity // 替代 @EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig {

    @Autowired
    private UserDetailsService userDetailsService;
    @Autowired
    private GzAuthenticationEntryPoint unauthorizedHandler;
    @Autowired
    private SystemYmlConfig systemYmlConfig;
    @Autowired
    private AuthenticationProvider authenticationProvider;

    /**
     * 定义安全过滤链
     */
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
                // 禁用 CSRF
                .csrf(AbstractHttpConfigurer::disable)
                // 配置 CORS
                .cors(cors -> cors.configurationSource(corsConfigurationSource()))
                // 异常处理
                .exceptionHandling(exception -> exception
                        .authenticationEntryPoint(unauthorizedHandler)
                )
                // 过滤请求
                .authorizeHttpRequests(
                        authorizeHttpRequests ->
                                // 对于登录login 注册register 验证码captchaImage 允许匿名访问
                                authorizeHttpRequests.requestMatchers("/api/anon/**",
                                                "/api/ossFiles/**",
                                                "/api/fans/fansLogin",
                                                "/api/wx/notify",
                                                "/api/tlpay/notify",
                                                "/api/mchApplyments/contractObtain",
                                                "/api/sms/**",
                                                "/api/scoreRecord/scoreRecordSync",
                                                "/api/redis/getFile",
                                                "/api/redis/upFile",
                                                "/api/redis/redis/getRedisValue",
                                                "/api/redis/redis/delRedis",
                                                "/api/redis/redis/setRedisExpireTime")
                                        .permitAll()
                                        .requestMatchers(
                                                HttpMethod.GET,
                                                "/"
                                        ).permitAll()
                                        .requestMatchers("/jmreport/**","/drag/**","/favicon.ico").permitAll()
                                        .requestMatchers("/error").permitAll()
                                        .requestMatchers("/swagger-resources/**").permitAll()
                                        .requestMatchers("/webjars/**").permitAll()
                                        .requestMatchers("/*/api-docs").permitAll()
                                        .requestMatchers("/druid/**").permitAll()
                                        .requestMatchers("/websocket/**").permitAll()
                                        .requestMatchers("/api/sms/smsCode").permitAll()
                                        // 除上面外的所有请求全部需要鉴权认证
                                        .anyRequest().authenticated()

                )// 添加自定义 JWT 过滤器
                .addFilterBefore(new GzAuthenticationTokenFilter(), UsernamePasswordAuthenticationFilter.class);

        http.userDetailsService(userDetailsService);
        // 禁用缓存
        http.headers(headers -> headers.cacheControl(cache -> {
        }));
        return http.build();
    }

    /**
     * 配置 CORS 跨域规则
     */
    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        if (systemYmlConfig.getAllowCors()) {
            CorsConfiguration config = new CorsConfiguration();
            config.setAllowCredentials(true);
            config.addAllowedOriginPattern(CorsConfiguration.ALL);
            config.addAllowedHeader(CorsConfiguration.ALL);
            config.addAllowedMethod(CorsConfiguration.ALL);
            source.registerCorsConfiguration("/**", config);
        }
        return source;
    }

    /**
     * 密码加密器
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    /**
     * 配置认证管理器
     */
    @Bean
    public AuthenticationManager authenticationManager(HttpSecurity http) throws Exception {
        AuthenticationManagerBuilder authenticationManagerBuilder =
                http.getSharedObject(AuthenticationManagerBuilder.class);
        authenticationManagerBuilder.authenticationProvider(authenticationProvider);
//        authenticationManagerBuilder
//                .userDetailsService(this.userDetailsService)
//                .passwordEncoder(passwordEncoder());
        return authenticationManagerBuilder.build();
    }
}